import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;


public class FourthScan {

	static int counter=0;
	static double confidence=0;

	public static byte[] OpenFile (String fileName) throws FileNotFoundException, IOException  {
		File file = new File(fileName);
        byte [] res = new byte[(int)file.length()];
        DataInputStream dis = new DataInputStream(new FileInputStream(file));
        dis.readFully(res);
        dis.close();
        
        return res;
	}
	
	public static boolean isWhiteSpace(char ch){

		if( !(ch>='a' && ch<='z') && !(ch>='A' && ch<='Z') )
			return true;
		
		return false;
	}
	
	public static byte[] JoitBytes (byte[] arr1, byte[] arr2){
		byte[] res = new byte[arr1.length + arr2.length];
		int i, j;
		for (i=0, j=0; i<arr1.length; i++, j++){
			res[j] = arr1[i];
		}
		
		for (i=0; i<arr2.length; i++, j++){
			res[j] = arr2[i];
		}
		
		return res;
	}
	
	public static byte[] TrimBytes(byte[] arr, int size){
		int i;
		byte[] res = new byte[size];
		
		int len = arr.length;
		
		for (i=0; i<size && i<len; i++)
			res[i] = arr[i];
		
		return res;
	}
	
	public static LargeKey Scan(LargeKey key, String IV, String cipher, int blockSize) throws FileNotFoundException, IOException {
		Stock st = new Stock();
		WordDictionary wd = new WordDictionary();
	
        byte [] iv = OpenFile(IV);
        byte [] cb = OpenFile(cipher);
        iv = TrimBytes(iv, blockSize);
        cb = JoitBytes(iv, cb);
             
        byte[] pt_byte =  OpenFile("Tranform.txt");
        String pt = Encrypt.BytesToStringASCII(pt_byte), temp_pt="";
        confidence = BruteForce.CalcSuccess(pt, wd);
        double temp_conf;
        
        int offset, finger, i , len;
        char ch, ch2=0, ch3;
        ch = ch2;
        
        boolean flag=true;
        LargeKey tempKey = new LargeKey(key);
        
        String word, prevWord="";
        len = pt.length();
        
        offset = 0;
        flag = true;
        while ( offset < len ){
        	while ( offset < len && isWhiteSpace(pt.charAt(offset)) ){
        		offset++;
        	}
        	
        	finger = offset;
        	while ( finger < len && !isWhiteSpace(pt.charAt(finger)) ){
        		finger++;
        	}
        	
        	word = pt.substring(offset, finger);
        	
        	flag = false;
        	if (word.length()>4 && wd.WordExists(word) && WordDictionary.HasCapitals(word) && !WordDictionary.OnlyCapitals(word) && word.compareTo(prevWord)!=0 ){
        		prevWord = word;
        		for (i=1; i<word.length(); i++){
        			if (word.charAt(i)>='A' && word.charAt(i)<='Z'){
        				       				
        				ch = (char)(word.charAt(i) + 32);
        				ch = (char) (((byte)(ch)) ^ cb[offset+i]);
        				
        				if ( ( (ch>='A' && ch<='Z') || (ch>='a' && ch<='z') ) && ( (((char)cb[offset+i+blockSize])>='A' && ((char)cb[offset+i+blockSize])<='Z') || (((char)cb[offset+i+blockSize])>='a' && ((char)cb[offset+i+blockSize])<='z') ) ){
			
        					ch2 = key.GetValue(ch, "plain");
        					ch3 = key.GetValue((char)cb[offset+i+blockSize], "cipher");
        					
        					tempKey = new LargeKey(key);
        					tempKey.SetValue(ch, ((char)cb[offset+i+blockSize]), "plain");
        					tempKey.SetValue(((char)cb[offset+i+blockSize]), ch, "cipher");
        					tempKey.SetValue(ch3, ch2, "plain");
        					tempKey.SetValue(ch2, ch3, "cipher");
        					flag = true;
        					
            				//System.out.println(offset + " : " + word + " : " + " : " + word.charAt(i) + "^" + cb[offset+i] + " : " + ch + " > " + tempKey.GetValue(ch, "plain") + " : " + ch3 + " > " + ch2 );
        					
        					break;
        				}
        			}
        		}
        		
        		if (flag){
	        		st.Transform(cipher,IV, tempKey, blockSize);
	        		pt_byte =  OpenFile("Tranform.txt");
	        		temp_pt = pt;
	                pt = Encrypt.BytesToStringASCII(pt_byte);
	                temp_conf = BruteForce.CalcSuccess(pt, wd);
	                
	                counter++;
	                
	                if (temp_conf >= confidence){
	                	offset = 0;
	                	key = tempKey;
	                	confidence = temp_conf;

	                }
	                else{
	                	offset = finger + 1;
	                	pt = temp_pt;
	                }
	                
        		}
        		else{
        			offset = finger + 1;
        		}
        	}
        	else{
        		offset = finger + 1;
        	}
        }
        
        
        
        return key;
	}
	
}
